<?php

namespace app\admin\middleware;

use app\common\Token;
use ReflectionClass;
use think\App;
use think\facade\Db;
use think\facade\Request;

class CheckAdmin
{
    protected $app;

    public function __construct(App $app)
    {
        $this->app = $app;
    }

    public function handle($request, \Closure $next)
    {
        // 获取当前请求的控制器和方法
        $controller = Request::controller();
        $action = Request::action();

        // 控制器完整类名
        $controllerClass = 'app\\admin\\controller\\' . $controller;

        // 利用反射获取控制器中的$noNeedLogin
        $reflection = new ReflectionClass($controllerClass);
        $noNeedLogin = [];
        if ($reflection->hasProperty('noNeedLogin')) {
            $property = $reflection->getProperty('noNeedLogin');
            $property->setAccessible(true);

            // 使用应用容器获取控制器实例
            $controllerInstance = $this->app->make($controllerClass);
            $noNeedLogin = $property->getValue($controllerInstance);
        }

        // 判断当前方法是否需要登录
        if (!in_array($action, $noNeedLogin)) {
            // 需要登录，校验token
            $token = $request->header('token');

            if (empty($token)) {
                throw new \app\common\NoLoginException('未登录');
            }

            $decoded = Token::verify($token);

            // 校验token中的admin_id是否存在
            if (!isset($decoded['id'])) {
                throw new \app\common\NoLoginException('token无效');
            }
            // 校验exp是否过期
            if ($decoded['exp'] < time()) {
                throw new \app\common\NoLoginException('token已过期');
            }

            // 判断当前admin权限
            $admin = Db::name('admin')->where('id', $decoded['id'])->find();
            if (empty($admin)) {
                throw new \app\common\NoLoginException('token无效');
            }

            // 判断admin的权限 1为管理员 默认有所有权限
            if ($admin['roleId'] != 1) {
                // 判断当前admin是否是禁用
                if ($admin['status'] != 1) {
                    throw new \app\common\NoLoginException('账号已禁用');
                }

                $permissions = Db::name('role')
                    ->alias('r')
                    ->join('rolepermission rp', 'r.id = rp.roleId')
                    ->join('permission p', 'rp.permissionId = p.id')
                    ->where('r.id', $admin['roleId'])
                    ->field('p.*')
                    ->select();

                // echo '/admin/' . strtolower($controller) . '/' . $action;

                // 校验当前请求的方法是否在权限列表中
                $hasPermission = false;

                foreach ($permissions as $permission) {
                    if ($permission['path'] == '/admin/' . strtolower($controller) . '/' . $action) {
                        $hasPermission = true;
                        break;
                    }
                }

                if (!$hasPermission) {
                    throw new \app\common\NoLoginException('权限不足');
                }
            }

            $request->uid = $decoded['id'];

            return $next($request);

        }

        return $next($request);
    }
}
